package com.zk.gencode;


import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

import javax.swing.text.html.parser.Entity;
import java.io.*;
import java.sql.*;
import java.util.*;

/**
 * Created by zhangkai on 15-6-9.
 */
public class Freemark {

    private static Map<String, String> dbType2JavaType = new HashMap();
    private static Map<String, String> dbType2JdbcType = new HashMap();

    private static ArrayList<DataStruct> tableData = new ArrayList();

    private static String[] tableNameList;
    private static String basePackage;
    private static String driverName;
    private static String url;
    private static String username;
    private static String password;

    public static void main(String[] args) throws Exception {
        init();
        for (String tableName : tableNameList) {
            initTableFiled(tableName);
            createFiles(tableName);
        }
    }

    public static void createFiles(String tableName) throws Exception {
        //基本路径
        String basePath = System.getProperty("user.dir") + "/src/main/java";

        //模板信息
        Configuration config = new Configuration();
        String templatePath = basePath + "/com/zk/gencode/template";
        config.setDirectoryForTemplateLoading(new File(templatePath));
        config.setSetting("defaultEncoding", "UTF-8");
        Map<String, Object> datas = new HashMap<String, Object>();
        datas.put("fieldList", tableData);
        datas.put("basePackage", basePackage);
        String resourceName = getJavaField(tableName);
        datas.put("resourceName", resourceName);
        String modelName = (char) (tableName.charAt(0) - 'a' + 'A') + getJavaField(tableName).substring(1);
        datas.put("modelName", modelName);
        datas.put("tableName", tableName);

        //基本路径
        String modelBasePath = basePath + "/" + basePackage.replace(".", "/") + "/" + resourceName;
        //判断是否 存在
        File dirFile = new File(modelBasePath);
        if (dirFile.exists()) {
            System.out.println("该模块已经存在，是否覆盖(y/n)");
            Scanner scanner = new Scanner(System.in);
            String commond = scanner.nextLine();
            scanner.close();;
            if(!"y".equals(commond)){
                return;
            }
        }

        //生成Entity
        String filePath = modelBasePath + "/entity/" + modelName + "Entity.java";
        createFile(datas, config, "entity.java.ftl", filePath);

        //生成mybatisXML
        filePath = System.getProperty("user.dir") + "/src/main/resources/mapper/mapper_" + resourceName + ".xml";
        createFile(datas,config, "mybatisMapper.xml.ftl", filePath);

        //生成IDAO
        filePath = modelBasePath + "/dao/I" + modelName + "Dao.java";
        createFile(datas,config, "idao.java.ftl", filePath);

        //生成IService
        filePath = modelBasePath + "/service/I" + modelName + "Service.java";
        createFile(datas,config, "iservice.java.ftl", filePath);

        //生成ServiceImpl
        filePath = modelBasePath + "/service/impl/" + modelName + "ServiceImpl.java";
        createFile(datas,config, "serviceimpl.java.ftl", filePath);

        //生成controller
        filePath = modelBasePath + "/controllor/" + modelName + "Controllor.java";
        createFile(datas,config, "controller.java.ftl", filePath);

        //打印修改信息
        System.out.println("请在application-dao.xml中增加如下配置：");
        System.out.println("<bean id=\"" + resourceName + "Dao\" class=\"org.mybatis.spring.mapper.MapperFactoryBean\">");
        System.out.println("    <property name=\"mapperInterface\" value=\"com.zk.shopping." + resourceName + ".dao.I" + modelName + "Dao\"/>");
        System.out.println("    <property name=\"sqlSessionFactory\" ref=\"sqlSessionFactory\"/>");
        System.out.println("</bean>");

    }

    //生成文件
    private static void createFile(Map<String, Object> datas, Configuration config, String templateName, String pathPath) throws Exception {
        //文件夹是否存在
        String dir = pathPath.substring(0, pathPath.lastIndexOf("/"));
        File dirFile = new File(dir);
        if (!dirFile.exists()) {
            dirFile.mkdirs();
        }

        Template temp = config.getTemplate(templateName);
        File outFile = new File(pathPath);
        Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile)));
        temp.process(datas, out);
        out.close();
        System.out.println("创建成功:" + pathPath);
    }


    private static void initTableFiled(String tableName) throws SQLException {
        String sql = "show full columns from " + tableName;
        Connection con = DriverManager.getConnection(url, username, password);
        Statement stmt = con.createStatement();
        ResultSet result = stmt.executeQuery(sql);
        while (result.next()) {
            String fieldName = result.getString("field").toLowerCase();
            String type = result.getString("type").split("\\(")[0];
            String comment = result.getString("comment");
            DataStruct temp = new DataStruct();

            temp.setFieldDb(fieldName);
            temp.setTypeDb(type);
            temp.setComment(comment);

            String javaField = getJavaField(fieldName);
            temp.setFieldJava(javaField);
            if (fieldName.startsWith("is") && type.equals("tinyint")) {
                type = "istinyint";
            }
            temp.setTypeJava(dbType2JavaType.get(type));
            temp.setFieldJavaMethod((char) (javaField.charAt(0) - 'a' + 'A') + javaField.substring(1));

            temp.setFieldJdbc(fieldName);
            temp.setTypeJdbc(dbType2JdbcType.get(type));

            tableData.add(temp);
        }
    }

    /**
     * 转换成驼峰式的明明方式
     *
     * @param field
     */
    public static String getJavaField(String field) {
        StringBuilder fileTemp = new StringBuilder();
        boolean isUpper = false;
        for (int i = 0; i < field.length(); i++) {
            if (field.charAt(i) == '_') {
                isUpper = true;
                continue;
            }
            if (isUpper) {
                fileTemp.append((char) (field.charAt(i) - 'a' + 'A'));
                isUpper = false;
            } else {
                fileTemp.append(field.charAt(i));
            }
        }
        return fileTemp.toString();
    }

    private static void init() throws Exception {
        initDBType();
        initProperties();
        initDBDriver();
    }

    private static void initDBDriver() throws ClassNotFoundException {
        //加载MySql的驱动类
        Class.forName(driverName);
    }

    private static void initProperties() throws Exception {
        //基本路径
        String basePath = System.getProperty("user.dir") + "/src/main/java";
//        String basePath = Thread.currentThread().getContextClassLoader().getResource("").getPath();
        //加载jdbc配置文件
        String jdbcfilePath = basePath + "/com/zk/gencode/properties/jdbc.properties";
        InputStream in = new FileInputStream(jdbcfilePath);
        Properties properties = new Properties();
        properties.load(in);
        in.close();
        driverName = properties.getProperty("jdbc.driverClassName");
        url = properties.getProperty("jdbc.url");
        username = properties.getProperty("jdbc.username");
        password = properties.getProperty("jdbc.password");

        //加载gencode配置文件
        String gencodefilePath = basePath + "/com/zk/gencode/properties/gencode.properties";
        in = new FileInputStream(gencodefilePath);
        properties = new Properties();
        properties.load(in);
        in.close();
        basePackage = properties.getProperty("gencode.basePackage");
        tableNameList = properties.getProperty("gencode.tableNameList").split(",");

    }

    private static void initDBType() {
        dbType2JavaType.put("int", "Integer");
        dbType2JavaType.put("varchar", "String");
        dbType2JavaType.put("bigint", "Long");
        dbType2JavaType.put("tinyint", "Integer");
        //以is开头的tinyint定义为bool
        dbType2JavaType.put("istinyint", "Boolean");
        dbType2JavaType.put("text", "String");

        dbType2JdbcType.put("int", "INTEGER");
        dbType2JdbcType.put("varchar", "VARCHAR");
        dbType2JdbcType.put("bigint", "BIGINT");
        dbType2JdbcType.put("tinyint", "TINYINT");
        //以is开头的tinyint定义为bool
        dbType2JdbcType.put("istinyint", "BOOLEAN");
        dbType2JdbcType.put("text", "VARCHAR");
    }
}
